package com.bitcointoolkit.web.service;

import com.bitcointoolkit.web.support.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * [类描述]
 *
 * @author caican
 * @date 2018/6/26
 */
@Service
public class AddrInfoServiceImpl implements AddrInfoService,InitializingBean {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    IAddrExecutor addrExecutorBlockdozer;

    @Autowired
    IAddrExecutor addrExecutorBtccom;

    @Override
    public Result<UtxoResult> listUtxo(String address, int pageNum, int pageSize) {
        IAddrExecutor addrExecutor = getExecutor();
        Result<UtxoResult> result = addrExecutor.getUtxoOfLegacy(address, pageNum, pageSize);
        if (!result.isSuccess()) {
            int t =failedNum.addAndGet(1);
            logger.warn("call " + addrExecutor.getClass().getSimpleName() +" failed(" + t + "):" +
                    result.getMsg());
            int retryTime = 1;
            result = retry(address, pageNum, pageSize, retryTime);

        } else {
            failedNum.set(0);
        }
        return result;
    }


    private Result<UtxoResult> retry(String address, int pageNum, int pageSize,int retryTime) {
        //TODO 并行查询
        logger.warn("retry.time: "+retryTime);
        IAddrExecutor addrExecutor = getExecutor();

        Result<UtxoResult> result = addrExecutor.getUtxoOfLegacy(address, pageNum, pageSize);
        if (!result.isSuccess()){
            logger.warn("retry "+retryTime+" failed:" + result.getMsg());
        } else {
            logger.info("retry "+retryTime+" successs:" );
        }
        return result;
    }

    private AtomicInteger failedNum = new AtomicInteger(0);
    /**
     * 按一定逻辑寻找最近访问最快的
     */
    private synchronized IAddrExecutor getExecutor() {
        if (currentExecutor == null) {
            currentExecutor = defaultExecutor;
            logger.info("using default executor:" + defaultExecutor.getClass().getSimpleName());
            return currentExecutor;
        }
        if (failedNum.get() > 5) {
            if (currentExecutor.equals(addrExecutorBtccom)) {
                currentExecutor = addrExecutorBlockdozer;
            } else if (currentExecutor.equals(addrExecutorBlockdozer)) {
                currentExecutor = addrExecutorBtccom;
            }

            failedNum.set(0);
            logger.info("change to use executor:" + currentExecutor.getClass().getSimpleName());
        }
        return currentExecutor;
    }

    private IAddrExecutor defaultExecutor;

    private IAddrExecutor currentExecutor;

    @Override
    public void afterPropertiesSet() throws Exception {
        defaultExecutor = addrExecutorBtccom;
    }
}
